home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / Text / Misc / Smiley / smiley.c < prev    next >
C/C++ Source or Header  |  1994-03-02  |  6KB  |  361 lines

  1. /*
  2.  * s m i l e y . c
  3.  * 
  4.  * DaviD W. Sanderson is to blame for this.
  5.  */
  6.  
  7. #include "smiley.h"
  8. #include "patchlevel.h"
  9.  
  10. /*
  11.  * macros
  12.  */
  13.  
  14. /*
  15.  * swrite() - write() a "string variable" (char *)
  16.  */
  17.  
  18. #define    swrite(fd, s)    (void) write((fd), (s), strlen(s))
  19.  
  20. /*
  21.  * lwrite() - write() a "string literal" (char [])
  22.  */
  23.  
  24. #define    lwrite(fd, lit)    (void) write((fd), (lit), sizeof(lit)-1)
  25.  
  26. /*
  27.  * PUTFACE() - write() a smiley and its description
  28.  */
  29.  
  30. #define    PUTFACE(fd, i)    swrite((fd), faces[i].face);    \
  31.             lwrite((fd), tab);        \
  32.             swrite((fd), faces[i].desc);    \
  33.             lwrite((fd), newline)
  34.  
  35. /*
  36.  * FD - file descriptor to which to write the output
  37.  */
  38.  
  39. #define FD    1
  40.  
  41. /*
  42.  * declarations
  43.  */
  44.  
  45. extern int      write();
  46. extern int      strlen();
  47. extern char    *bsearch();
  48.  
  49. /*
  50.  * definitions
  51.  */
  52.  
  53. static char     ENVAR[] = "SMILEY";
  54. static char     tab[] = "\t";
  55. static char     newline[] = "\n";
  56.  
  57. /*
  58.  * facecmp() - comparison routine for using bsearch()
  59.  */
  60. int
  61. facecmp(f1, f2)
  62.     struct smiley  *f1;
  63.     struct smiley  *f2;
  64. {
  65.     return strcmp(f1->face, f2->face);
  66. }
  67.  
  68. /*
  69.  * fsearch() - return index of face, or -1 on failure
  70.  * 
  71.  * Note that this assumes that there will be at most one entry in
  72.  * faces[] for a particular smiley.  It also assumes that faces[] is
  73.  * sorted in ascending order.
  74.  */
  75. int
  76. fsearch(s)
  77.     char           *s;
  78. {
  79.     struct smiley   f;
  80.     struct smiley  *ans;
  81.  
  82.     f.face = s;
  83.     ans = (struct smiley *) bsearch(
  84.         (char *) &f,
  85.         (char *) faces, (unsigned) nfaces, sizeof faces[0],
  86.         facecmp);
  87.  
  88.     if (ans)
  89.         return ans - faces;
  90.     else
  91.         return -1;
  92. }
  93.  
  94. /*
  95.  * explain() - look through the list of smileys for the given face.
  96.  * 
  97.  * If it is found, then print out the description.
  98.  * 
  99.  * The return value is zero if the face is not found, nonzero otherwise.
  100.  */
  101. static int
  102. explain(s)
  103.     char           *s;
  104. {
  105.     int             i;
  106.  
  107.     if((i = fsearch(s)) == -1)
  108.         return 0;
  109.  
  110.     PUTFACE(FD, i);
  111.     return 1;
  112. #if 0
  113.     int        found = 0;
  114.  
  115.     for (i = 0; i < nfaces; i++)
  116.     {
  117.         extern int      strcmp();
  118.  
  119.         if (strcmp(s, faces[i].face) == 0)
  120.         {
  121.             found = 1;
  122.             PUTFACE(FD, i);
  123.         }
  124.     }
  125.     return found;
  126. #endif
  127. }
  128.  
  129. /*
  130.  * main() - main program
  131.  */
  132.  
  133. main(ac, av)
  134.     int             ac;
  135.     char          **av;
  136. {
  137.     extern char    *optarg;
  138.     extern int      optind;
  139.     extern int      opterr;
  140.  
  141.     char           *args = "Velf";
  142.     int             Vflag = 0;
  143.     int             eflag = 0;
  144.     int             lflag = 0;
  145.     int             fflag = 0;
  146.     int             errflag = 0;
  147.     int             c;
  148.  
  149.     /*
  150.      * process command-line options
  151.      */
  152.     while ((c = getopt(ac, av, args)) != -1)
  153.     {
  154.         switch (c)
  155.         {
  156.         case 'V':    /* version */
  157.             Vflag = 1;
  158.             break;
  159.         case 'e':    /* environment */
  160.             eflag = 1;
  161.             break;
  162.         case 'l':    /* list */
  163.             lflag = 1;
  164.             break;
  165.         case 'f':    /* face only */
  166.             fflag = 1;
  167.             break;
  168.         case '?':
  169.             errflag = 1;
  170.             break;
  171.         }
  172.     }
  173.     if (errflag)
  174.     {
  175.         static char     msg0[] = "usage: ";
  176.         static char    *msg1[] =
  177.         {
  178.             " [-V] [-e] [-l] [-f] [smiley ...]\n",
  179.             "where:\t-V\tprint program version\n",
  180.             "\t-e\texplain the face in $",
  181.             (char *) 0
  182.         };
  183.         static char    *msg2[] =
  184.         {
  185.             "\n",
  186.             "\t-l\tlist all the smileys\n",
  187.             "\t-f\tprint a random smiley, face only\n",
  188.             "\tsmiley\texplain the given smileys\n",
  189.             "(no args)\tprint a random smiley\n",
  190.             (char *) 0
  191.         };
  192.  
  193.         char           **p;
  194.  
  195.         lwrite(FD, msg0);
  196.         swrite(FD, av[0]);
  197.  
  198.         for (p = msg1; *p; p++)
  199.             swrite(FD, *p);
  200.  
  201.         lwrite(FD, ENVAR);
  202.  
  203.         for (p = msg2; *p; p++)
  204.             swrite(FD, *p);
  205.  
  206.         return 1;
  207.     }
  208.  
  209.     /*
  210.      * perform command-line options
  211.      */
  212.  
  213.     /*
  214.      * Vflag - print version information
  215.      */
  216.     if (Vflag)
  217.     {
  218.         static char     stat0[] = " faces, ";
  219.         static char     stat1[] = " definitions\n";
  220.         char *num;
  221.         int i;
  222.         unsigned long ndefs;
  223.         extern char *ltoa();
  224.  
  225.         swrite(FD, av[0]);
  226.         lwrite(FD, version);
  227.  
  228.         /*
  229.          * Print counts of the smiley faces and definitions
  230.          * The definitions for a smiley are separated by
  231.          * newlines, but not terminated by newlines.
  232.          */
  233.         num = ltoa((unsigned long)nfaces, 10);
  234.         swrite(FD, num);
  235.         lwrite(FD, stat0);
  236.  
  237.         ndefs = nfaces;
  238.         for (i=0; i<nfaces; i++)
  239.         {
  240.             char *def;
  241.  
  242.             for (def = faces[i].desc; *def; def++)
  243.             {
  244.                 if (*def == '\n')
  245.                     ndefs++;
  246.             }
  247.         }
  248.         num = ltoa(ndefs, 10);
  249.         swrite(FD, num);
  250.         lwrite(FD, stat1);
  251.  
  252. #ifdef __DATE__
  253. #ifdef __TIME__
  254.         {
  255.             static char     when0[] = "last compiled ";
  256.             static char     when1[] = __TIME__;
  257.             static char     when2[] = " ";
  258.             static char     when3[] = __DATE__;
  259.             static char     when4[] = "\n";
  260.  
  261.             lwrite(FD, when0);
  262.             lwrite(FD, when1);
  263.             lwrite(FD, when2);
  264.             lwrite(FD, when3);
  265.             lwrite(FD, when4);
  266.         }
  267. #endif
  268. #endif
  269.  
  270.         return 0;
  271.     }
  272.  
  273.     /*
  274.      * eflag - explain $SMILEY
  275.      */
  276.     if (eflag)
  277.     {
  278.         extern char    *getenv();
  279.         int            unknown = 1;
  280.         char           *str;
  281.  
  282.         if ((str = getenv(ENVAR)) != (char *)0)
  283.         {
  284.             if(explain(str) != 0)
  285.                 unknown = 0;
  286.         }
  287.         else
  288.         {
  289.             static char     notset[] = " not set\n";
  290.  
  291.             lwrite(FD, ENVAR);
  292.             lwrite(FD, notset);
  293.         }
  294.         return unknown;
  295.     }
  296.  
  297.     /*
  298.      * lflag - list smileys
  299.      */
  300.     if (lflag)
  301.     {
  302.         int             i;
  303.  
  304.         for (i = 0; i < nfaces; i++)
  305.         {
  306.             PUTFACE(FD, i);
  307.         }
  308.         return 0;
  309.     }
  310.  
  311.     /*
  312.      * literal smileys - try to explain them
  313.      *
  314.      * In this case the exit status is the number of smileys
  315.      * that were not found.
  316.      */
  317.     if (optind < ac)
  318.     {
  319.         int    unknown = 0;
  320.  
  321.         for (; optind < ac; optind++)
  322.         {
  323.             if(!explain(av[optind]))
  324.                 unknown++;
  325.         }
  326.  
  327.         return unknown;
  328.     }
  329.  
  330.     /*
  331.      * otherwise - generate a random smiley
  332.      */
  333.     {
  334.         extern int      rand();
  335.         extern void     srand();
  336.         extern long     time();
  337.         extern int      getpid();
  338.  
  339.         char           *f;
  340.  
  341.         /*
  342.          * seed with the current time + the pid. (The pid
  343.          * prevents smileys started at identical times from
  344.          * getting the same random seed)
  345.          */
  346.         srand((unsigned) time((long *)0) + (unsigned) getpid());
  347.         f = faces[rand() % nfaces].face;
  348.  
  349.         if (fflag)
  350.         {
  351.             swrite(FD, f);
  352.             lwrite(FD, newline);
  353.         }
  354.         else
  355.         {
  356.             (void) explain(f);
  357.         }
  358.     }
  359.     return 0;
  360. }
  361.